#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;

class Stack1{
private:
    int * _data;
};
class Stack2{
private:
    double * _data;
};
//=================这是没有引入模板之前的写法==================
//引入了模板之后，那么只需要编写一个即可
//根据调用情况，进行自动实例化
//编写了一个类模板，类型使用T来充当，可以是int、也可以是double
//capacity=10表示的是栈的容量
//template <class T, class Allocator = std::allocator<T>>
//class vector;
//vector<int> number;
template <class T, int capacity = 10>
class Stack{
public:
    Stack()
    :_data(new T[capacity]())
    ,_top(-1)
    {
       cout << "Stack()" << endl; 
    }

    ~Stack(){
        cout << "~Stack()" << endl;
        if(_data){
            delete [] _data;
            _data = nullptr;
        }
    }
    bool empty() const;
    bool full() const;
    void push(const T &);
    void pop();
    T top();

private:
    T * _data;
    int _top;
};

template <class T, int capacity>
bool Stack<T,capacity>::empty() const{
    return _top == -1;
}
template <class T, int capacity>
bool Stack<T,capacity>::full() const{
    return _top == capacity - 1;
}
template <class T, int capacity>
void Stack<T,capacity>::push(const T & value){
    _data[++_top] = value;
}
template <class T, int capacity>
void Stack<T,capacity>::pop(){
    --_top;
}
template <class T, int capacity>
T Stack<T,capacity>::top(){
    return _data[_top];
}
void test(){
    //只需要编写一份代码，那么便可以实例化出三份不同的类
    //使用模板之后，并不是说这三个类不用存在了，而是编译器帮助我们去生成
    Stack<int, 20> sta1;
    sta1.push(1);
    sta1.push(2);
    sta1.push(3);
    sta1.push(4);
    sta1.push(5);
    for(int i = 0; i < 5; ++i){
        cout << sta1.top() << endl;
        sta1.pop();
    } 

    Stack<double> sta2;

    Stack<string> sta3;
    sta3.push("hello");
    sta3.push("c++");
    sta3.push("world");
    for(size_t i = 0; i < 3; ++i){
        cout << sta3.top() << endl;
        sta3.pop();
    }
}

int main()
{
    test();
    return 0;
}

